package cn.xinfei.xdecision.engine.runner.expressions;

import cn.xinfei.xdecision.common.model.component.guiderule.RuleLoopGroupAction;
import cn.xinfei.xdecision.common.model.component.guiderule.vo.RuleConditionVo;
import cn.xinfei.xdecision.common.model.enginex.runner.ExpressionParam;
import cn.xinfei.xdecision.common.utils.constant.strategyx.RuleConst;
import cn.xinfei.xdecision.common.utils.util.runner.jeval.EvaluationException;
import cn.xinfei.xdecision.engine.runner.context.AmmunitionDepot;
import cn.xinfei.xdecision.engine.runner.context.PipelineContextHolder;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;

import java.util.*;

public class RuleConditionExecutor {
    //执行规则的条件
    public static boolean executeRuleCondition(String nodeCode, RuleConditionVo ruleCondition) throws EvaluationException {
        Integer conditionType = ruleCondition.getConditionType();
        boolean result = false;
        switch (conditionType) {
            case RuleConst.RELATION_CONDITION:
                //关系条件节点 &&和||
            case RuleConst.LOOP_RESULT_CONDITION:
                //循环结果的条件
            case RuleConst.CONDITION_RESULT_CONDITION:
                //条件组节点
                result = executeRelation(nodeCode, ruleCondition);
                break;
            case RuleConst.EXPRESSION_CONDITION:
                //表达式条件节点
                result = executeExpression(ruleCondition);
                break;
            case RuleConst.LOOP_CONDITION:
                //循环条件根节点
                result = executeLoop(nodeCode, ruleCondition);
                break;
            case RuleConst.CONDITION_GROUP_CONDITION:
                //条件组根节点
                result = executeCondGroup(nodeCode, ruleCondition);
                break;
        }
        return result;
    }

    //执行条件组
    private static boolean executeCondGroup(String nodeCode, RuleConditionVo ruleCondition) throws EvaluationException {
        //取出子条件
        List<RuleConditionVo> children = ruleCondition.getChildren();
        //存储命中条数
        int hitNum = 0;
        if (children == null) {
            return false;
        }
        //执行条件组中条件列表，命中则添加命中条数
        for (RuleConditionVo child : children) {
            boolean childResult = executeRuleCondition(nodeCode, child);
            if (childResult) {
                hitNum++;
            }
        }
        //获取条件组命中条件，为null直接不命中
        RuleConditionVo condGroup = ruleCondition.getCondGroupResultCondition();
        if (condGroup == null) {
            return false;
        }
        //传入命中条件和组内命中条数执行并返回
        Map<String, Object> map = new HashMap<>();
        //将命中条数存入map然后判断执行结果
        map.put("hitNum", hitNum);
        return executeRuleCondition(nodeCode, condGroup);
    }

    //关系条件节点 &&和||
    private static boolean executeRelation(String nodeCode, RuleConditionVo ruleCondition) throws EvaluationException {
        //获取关系逻辑
        String logical = ruleCondition.getLogical();
        //处理子逻辑
        List<RuleConditionVo> children = ruleCondition.getChildren();

        boolean result = false;
        switch (logical) {
            case "||":
                result = false;
                for (RuleConditionVo child : children) {
                    boolean childResult = executeRuleCondition(nodeCode, child);
                    if (childResult) {
                        return true;
                    }
                }
                break;
            case "&&":
                result = true;
                for (RuleConditionVo child : children) {
                    boolean childResult = executeRuleCondition(nodeCode, child);
                    if (!childResult) {
                        return false;
                    }
                }
                break;
        }
        return result;
    }

    //表达式条件节点
    private static boolean executeExpression(RuleConditionVo ruleCondition) throws EvaluationException {
//        String executionLogic = ruleCondition.getExecutionLogic();
        boolean result = false;
        ExpressionParam expressionParam = new ExpressionParam();
        //复制执行的关键参数到统一入参
        BeanUtils.copyProperties(ruleCondition, expressionParam);
        expressionParam.setFieldEn(ruleCondition.getFieldCode());
        result = ExpressExecutor.getExpressionResult(expressionParam);
        return result;
    }

    //循环条件根节点
    private static boolean executeLoop(String nodeCode, RuleConditionVo ruleCondition) throws EvaluationException {
        List<RuleConditionVo> children = ruleCondition.getChildren();
        String fieldEn = ruleCondition.getFieldCode();

        //对循环中每个条件进行处理
        String[] split = fieldEn.split("\\.");
        //从map中取元素返回最终取到的对象
//        Object obj = PipelineContextHolder.getValueByKey(fieldEn);
        Object obj = AmmunitionDepot.getValueByKeyFromRemote(fieldEn);
        List arrayList = new ArrayList();
        if (obj != null) {
            arrayList.addAll(JSON.parseObject(JSON.toJSONString(obj), ArrayList.class));
        }
        //取不到这个数组
        if (arrayList.isEmpty()) {
            return false;
        }
        //拼接当前对象的key
        String currentKey = "%" + split[split.length - 1] + "%";
        for (RuleConditionVo child : children) {
            List<RuleLoopGroupAction> loopGroupActions = child.getLoopGroupActions();
            // 调用for循环条件下的操作,并且将其存入input中
            for (RuleLoopGroupAction loopGroupAction : loopGroupActions) {
                initLoopGroupAction(nodeCode, loopGroupAction);
            }
        }
        //将循环时的当前对象存入input
//            contextPot.putInContext(currentKey, currentObj);
        //循环执行当前for中的每个判断单元
        for (RuleConditionVo child : children) {
            if (executeRuleCondition(nodeCode, child)) {
                List<RuleLoopGroupAction> loopGroupActions = child.getLoopGroupActions();
                // 调用for循环条件下的操作,并且将其存入input中
                for (RuleLoopGroupAction loopGroupAction : loopGroupActions) {
                    saveLoopGroupAction(nodeCode, loopGroupAction);
                }
            }
        }
        //计算for的返回结果
        RuleConditionVo loopResultCondition = ruleCondition.getLoopResultCondition();
        boolean result = executeRuleCondition(nodeCode, loopResultCondition);
        return result;
    }

    //保存循环规则的动作
    private static void saveLoopGroupAction(String nodeCode, RuleLoopGroupAction loopGroupAction) {
        Integer actionType = loopGroupAction.getActionType();
        String actionKey = loopGroupAction.getActionKey();
        String actionValue = loopGroupAction.getActionValue();
        if (actionType == null) {
            return;
        }
        switch (actionType) {
            case RuleConst.LOOP_GROUP_ACTION_TYPE_SUM:
                Integer count = 1;
                Object valueByKeyFromRemote = AmmunitionDepot.getValueByKeyFromRemote(actionKey);
                if(null!=valueByKeyFromRemote) {
                    String val = valueByKeyFromRemote.toString();
                    if(StringUtils.isNotEmpty(val)&&StringUtils.isNumeric(val)){
                        count = count + Integer.parseInt(val);
                    }
                    PipelineContextHolder.putInContext(nodeCode, actionKey, count);
                }
//                if (PipelineContextHolder.containsKey(actionKey) && StringUtils.isNumeric(PipelineContextHolder.getValueByKey(actionKey).toString())) {
//                    count = count + Integer.parseInt(PipelineContextHolder.getValueByKey(actionKey).toString());
//                }
//                PipelineContextHolder.putInContext(nodeCode, actionKey, count);
                break;
            case RuleConst.LOOP_GROUP_ACTION_TYPE_ASSIGNMENT:
                //赋值待添加
                break;
            case RuleConst.LOOP_GROUP_ACTION_TYPE_OUT_CONST:
                PipelineContextHolder.putInContext(nodeCode, actionKey, actionValue);
                break;
            case RuleConst.LOOP_GROUP_ACTION_TYPE_OUT_VARIABLE:
                PipelineContextHolder.putInContext(nodeCode, actionKey, AmmunitionDepot.getValueByKeyFromRemote(actionValue));
                break;
        }
    }


    private static void initLoopGroupAction(String nodeCode, RuleLoopGroupAction loopGroupAction) {
        Integer actionType = loopGroupAction.getActionType();
        String actionKey = loopGroupAction.getActionKey();
        String actionValue = loopGroupAction.getActionValue();
        if (actionType == null) {
            return;
        }
        switch (actionType) {
            case RuleConst.LOOP_GROUP_ACTION_TYPE_SUM:
                PipelineContextHolder.putInContext(nodeCode, actionKey, 0);
                break;
            case RuleConst.LOOP_GROUP_ACTION_TYPE_ASSIGNMENT:
                //赋值待添加
                break;
            case RuleConst.LOOP_GROUP_ACTION_TYPE_OUT_CONST:
                PipelineContextHolder.putInContext(nodeCode, actionKey, "");
                break;
            case RuleConst.LOOP_GROUP_ACTION_TYPE_OUT_VARIABLE:
                PipelineContextHolder.putInContext(nodeCode, actionKey, new HashSet<>());
                break;
        }
    }
}
